﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MantisToPivotalTracker.MantisService;
using PivotalTracker.FluentAPI.Domain;
using PivotalTracker.FluentAPI.Service;
using System.Net;

namespace MantisToPivotalTracker
{
    class Program
    {       
        static void Main(string[] args)
        {
            var lPivotal = new PivotalTrackerFacade(new Token(Custom.PIVOTAL_APIKEY));
            var lPivotalProject = lPivotal.Projects().Get(Custom.PIVOTAL_PROJECT_ID);

            using (var lMantis = new MantisConnect())
            {
                TransfertFromMantisToPivotal(lPivotalProject, lMantis);

            }

            lPivotalProject.DeliverAllFinishedStories();
            lPivotalProject.AcceptAllDeliveredStories();

            //  Console.ReadKey();
        }

        #region Converter Mantis To Pivotal (can be adapted)
       

        //TODO: Can be adapted
        private static StoryStateEnum ConvertStoryStatus(IssueData p, StoryTypeEnum type)
        {
            //Mantis status
            //10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,80:resolved,90:closed
            switch (p.status.id)
            {
                case "10":
                    return StoryStateEnum.Unscheduled;
                case "20":
                    //Chore cannot be rejected
                    return  type != StoryTypeEnum.Chore ?  StoryStateEnum.Unscheduled : StoryStateEnum.Rejected;
                case "30":
                    return StoryStateEnum.Unscheduled;
                case "40":
                    return  StoryStateEnum.Started;
                case "50":
                    return  StoryStateEnum.Started;
                case "80":
                    //Chore cannot be finished
                    return  type == StoryTypeEnum.Chore ? StoryStateEnum.Accepted : StoryStateEnum.Finished;
                case "90":
                    return  StoryStateEnum.Accepted ;
                default:
                    return  StoryStateEnum.Unscheduled;
            }
        }

        //TODO: Can be adapted
        private static MembershipRoleEnum GetPivotalRole(string accessLevel)
        {
            switch (accessLevel)
            {
                case "viewer":
                    return MembershipRoleEnum.Viewer;
                case "reporter":
                case "updater":
                case "developer":
                    return MembershipRoleEnum.Member;
                case "manager":
                case "administrator":
                    return MembershipRoleEnum.Owner;
                default:
                    return MembershipRoleEnum.Viewer;
            }
        }

        private static void AssignRoles(MantisConnect lMantis, ProjectFacade lPivotalProject)
        {
            var mantisAccessLevels = new string[]
            {
                "administrator",
                "manager",    
                "developer",
                "updater",
                "reporter",
                "viewer"
            };

        

            //retrieve all pivotal user from project memberships
            var pivotalMembers = new List<string>();
            lPivotalProject.Membership().All(members => pivotalMembers.AddRange(members.Select(m=>m.Person.Name)));

            foreach (var al in mantisAccessLevels)
            {
                //retrieve user by access level
                var lUsers = lMantis.mc_project_get_users(Custom.MANTIS_LOGIN, Custom.MANTIS_PASSWORD, Custom.MANTIS_PROJECT_ID, al);
                var pivotalRole = GetPivotalRole(al);

                
                foreach (var u in lUsers)
                {
                    //check if user exists in Pivotal
                    var pivotalUser = Custom.GetPivotalUser(u.name);
                    if (pivotalUser == null)
                        continue;

                    //check if some memberships exist for this user
                    if (pivotalMembers.Where(n => n == pivotalUser.Name).Count() != 0)
                        continue;

                    //add membership
                    Membership lNewMembership = new Membership()
                                        {
                                            MembershipRole = pivotalRole,
                                            Person = pivotalUser
                                        };
                    lPivotalProject.Membership()
                    .Add(lNewMembership);

                    pivotalMembers.Add(lNewMembership.Person.Name);
                }
            }
        }
  
        #endregion


        #region Main workflow
        private static void TransfertFromMantisToPivotal(ProjectFacade lPivotalProject, MantisConnect lMantis)
        {
            lMantis.Url = Custom.MANTIS_BASE_URL + "/api/soap/mantisconnect.php";

             AssignRoles(lMantis, lPivotalProject);  //comment it when testing

            var page = 1;
            const int nbPerPage = 10;
            var lastId = "";

            IssueData[] issues = lMantis.mc_project_get_issues(Custom.MANTIS_LOGIN, Custom.MANTIS_PASSWORD, Custom.MANTIS_PROJECT_ID, page.ToString(), nbPerPage.ToString());


            while (issues != null && issues.Length > 0)
            {
                if (lastId == issues[0].id)
                    break;

                lastId = issues[0].id;

                var stories = lPivotalProject.Stories();

                foreach (var p in issues)
                {
                    StoryTypeEnum type = Custom.ConvertStoryType(p);
                    StoryStateEnum state = ConvertStoryStatus(p, type);

                    var owner = Custom.GetPivotalUser(p.handler != null ? p.handler.name : null);
                    stories
                        .Create()
                            .SetName(p.summary)
                            .SetDescription(String.Format("*{0} ({1}):*\n{2}\n\n{3}", p.reporter.name, p.date_submitted, p.description, p.additional_information))
                            .SetType(type)
                            .SetLabel(p.category)
                            .SetOwner(owner == null ? "" : owner.Name)
                            .SetEstimate(type != StoryTypeEnum.Feature ? 0 : 3) //Only feature can have an estimation
                        .Save()
                        .Do((t, s) =>
                                {
                                    //Add a note that contains mantis url source
                                    t.AddNote(String.Format("Ref Mantis: {1}/view.php?id={0}", p.id, Custom.MANTIS_BASE_URL));

                                    //Add a pivotal note for each mantis note.
                                    //Reporter and submission date are embedded into the note
                                    foreach (var n in p.notes)
                                    {
                                        t.AddNote(String.Format("*Created by {0} ({2}):*\n{1}", n.reporter.name, n.text, n.date_submitted));
                                    }

                                    //Upload attachments
                                    var i = 0;
                                    foreach (var a in p.attachments)
                                    {
                                        using (var web = new WebClient())
                                        {
                                            var data = web.DownloadData(a.download_url);
                                            t.UploadAttachment(data, a.filename, a.content_type);
                                        }

                                        i++;
                                        //Create a note for each attachment (because you can't associate info from API)
                                        t.AddNote(String.Format("Attachment {3}:\n  Submitted :{4}\n  Name:{0}\n  Content-Type:{5}\n  Size:{1}\n  Url:{2}\n", a.filename, a.size, a.download_url, i, a.date_submittedSpecified ? a.date_submitted.ToString() : "", a.content_type));

                                    }
                                })
                        .Update(s =>
                            {
                                if (p.attachments.Count() > 0)
                                    s.Labels.Add("attach");

                                s.CurrentState = state;
                            })
                        .Done();
                }

                page++;
                issues = lMantis.mc_project_get_issues(Custom.MANTIS_LOGIN, Custom.MANTIS_PASSWORD, Custom.MANTIS_PROJECT_ID, page.ToString(), nbPerPage.ToString());
            }
        }
        #endregion





    }
}
